from pathlib import Path

from django.db import models
from django.core.validators import FileExtensionValidator, MinLengthValidator
from django.contrib.auth.models import AbstractUser

from core.utils.storage import dynamic_upload


class User(AbstractUser):
    pass


# This is the best solution to assign multiple unicode ranges
# while keeping admin interface easy to use
# with support of all database engines
class UnicodeRange(models.Model):
    start = models.CharField(
        max_length=5,
        validators=(
            MinLengthValidator(4),
        )
    )
    end = models.CharField(max_length=5, default='', blank=True)
    name = models.CharField(default='', blank=True, max_length=64)

    @property
    def range(self) -> str:
        return f'{self.start}-{self.end}' if self.end else self.start

    def __str__(self) -> str:
        return f'{self.name} ({self.range})'

    class Meta:
        unique_together = ('start', 'end')


class Font(models.Model):
    name = models.SlugField(max_length=64, unique=True, db_index=True)

    def __str__(self) -> str:
        return self.name


class FontFile(models.Model):
    OTF = 'otf'

    TTF = 'ttf'

    WOFF = 'woff'

    WOFF2 = 'woff2'

    FORMATS = (
        (OTF, 'otf'),
        (TTF, 'ttf'),
        (WOFF, 'woff'),
        (WOFF2, 'woff2')
    )

    file = models.FileField(
        upload_to=dynamic_upload('fonts/'),
        validators=(
            FileExtensionValidator([key for key, _ in FORMATS]),
        )
    )
    name = models.CharField(default='', blank=True, max_length=32)
    unicode_ranges = models.ManyToManyField(
        UnicodeRange,
        related_name='files',
        blank=True
    )
    font = models.ForeignKey(
        Font,
        on_delete=models.CASCADE,
        related_name='files'
    )

    @property
    def suffix(self):
        path = Path(self.file.path)

        return path.suffix

    @property
    def format(self):
        return self.suffix[1:]

    def __str__(self) -> str:
        return self.name or self.font.name
